package cc.shacocloud.kotlin.tools.jdbc

import cc.shacocloud.kotlin.tools.Slf4j
import com.zaxxer.hikari.HikariDataSource
import java.sql.Connection

/**
 * jdbc 数据源
 * @author 思追(shaco)
 */
@Slf4j
class JdbcDataSource(properties: JdbcProperties) : AutoCloseable {

    private val datasource = HikariDataSource(properties)

    /**
     * jdbc 使用事务的高阶函数
     * @author 思追(shaco)
     */
    fun <R> useTransactions(handler: JdbcTemplate.() -> R): R {
        return useConnection { connection ->
            connection.autoCommit = false

            val result = try {
                with(JdbcTemplate(connection), handler)
            } catch (e: Throwable) {

                try {
                    connection.rollback()
                } catch (e1: Throwable) {
                    e.addSuppressed(e1)
                }

                throw e
            }

            connection.commit()

            result
        }
    }

    /**
     * jdbc 使用自动提交
     * @author 思追(shaco)
     */
    fun <R> useAutoCommit(handler: JdbcTemplate.() -> R): R {
        return useConnection { connection ->
            with(JdbcTemplate(connection), handler)
        }
    }

    /**
     * jdbc 使用链接
     * @author 思追(shaco)
     */
    fun <R> useConnection(handler: (connection: Connection) -> R): R {
        return datasource.connection.use(handler)
    }

    override fun close() {
        datasource.close()
    }

}